import 'dart:math';

import 'package:tile/data/coordinate.dart';
import 'package:tile/tile.dart';

/// 将1、2象限的题目旋转到第4象限
String transformSgfToRightBottomCorner(String sgf, int boardSize) {
  if (boardSize == 19) {
    String tempSgf =
        sgf.trim().replaceAllMapped(RegExp(r'[\n ]'), (match) => '');
    sgf = tempSgf;
    int bound = sgf.sgfGetQuadrant(boardSize: boardSize, deleteAnswer: false);
    if (bound == 3 || bound == 4) {
      return sgf;
    }
    for (int i = 0; i < sgf.length; i++) {
      if (i > 2 && i < sgf.length - 1) {
        if ((sgf[i - 2] == '[' && sgf[i + 1] == ']') ||
            (sgf[i - 2] == '[' && sgf[i + 1] == ':') ||
            (sgf[i - 2] == ',' && sgf[i + 1] == ':')) {
          var valueY = sgf[i];
          if (bound == 2) {
            var valueX = sgf[i - 1];
            var codeValueX = valueX.codeUnitAt(0);
            if (codeValueX <= 's'.codeUnitAt(0) &&
                codeValueX >= 'a'.codeUnitAt(0)) {
              var x = String.fromCharCode(
                  's'.codeUnitAt(0) - valueX.codeUnitAt(0) + 'a'.codeUnitAt(0));
              tempSgf = tempSgf.replaceRange(i - 1, i, x);
            }
          }
          var codeValueY = valueY.codeUnitAt(0);
          if (codeValueY <= 's'.codeUnitAt(0) &&
              codeValueY >= 'a'.codeUnitAt(0)) {
            var y = String.fromCharCode(
                's'.codeUnitAt(0) - valueY.codeUnitAt(0) + 'a'.codeUnitAt(0));
            tempSgf = tempSgf.replaceRange(i, i + 1, y);
          }
        }
      }
    }
    return tempSgf;
  } else {
    return sgf;
  }
}

extension IntExt on int {
  String toStr(int num) {
    if (this < 0 || this > 19) {
      // throw Exception("num必须大于等于0，小于等于19");
    }
    if (this < 10) {
      return "0$this";
    }
    return "$this";
  }
}

extension Ext on Board {
  String get allStep {
    String steps = "";
    currNode.backStepList().forEach((element) {
      // [3,4] => +1704
      steps += element.bw == Board.BLACK ? "+" : "-";
      if (element.x == 0 && element.y == 0) {
        steps += "0000";
      } else {
        steps += element.x == 0
            ? element.x.toStr(2)
            : (getBoardSize() - element.x + 1).toStr(2);
        steps += element.y.toStr(2);
      }
    });
    return steps;
  }

  void showYzSteps(String steps,
      {bool refreshUI = true, bool forceChess = true}) {
    if (steps.length % 5 != 0) {
      throw Exception("错误的棋谱：$steps");
    }
    int num = steps.length ~/ 5;

    SgfNode node = currNode;

    for (int i = 0; i < num; i++) {
      final step = steps.substring(i * 5, i * 5 + 5);

      int bw = step.substring(0, 1) == "+" ? Board.BLACK : Board.WHITE;
      int x = 0;
      int y = 0;
      if (!step.contains('0000')) {
        x = getBoardSize() - int.parse(step.substring(1, 3)) + 1;
        y = int.parse(step.substring(3, 5));
      }

      nextColor = bw;
      node = node.addChild(SgfNode.fromXY(x, y, bw)..markOrderState(1));
      // putNode(SgfNode.fromXY(x, y, bw), forceChess: forceChess);
    }
    showSgfNode(node);
    if (refreshUI) {
      postEvent('showYzSteps');
    }
  }

  bool put(int x, int y) {
    return putNode(SgfNode.fromXY(x, y, nextColor));
  }

  showCoordinate(
    int x,
    int y, {
    bool refreshUI = true,
    bool clickByUser = false,
  }) {
    putNode(SgfNode.fromXY(x, getBoardSize() - y + 1, nextColor),
        refreshUI: refreshUI, clickByUser: clickByUser, forceChess: true);
  }
}

extension SGFStringExt on String {
  SgfNode parseToSgfNode() {
    return SGFParser().parse(this).parse();
  }

  ///C16转位置1603
  String? gtpToYz() {
    if (toLowerCase() == 'pass') {
      return '0000';
    }
    if (RegExp(r'[A-Z]\d{1,2}').hasMatch(this)) {
      String alpha = 'ABCDEFGHJKLMNOPQRST';
      int x = alpha.indexOf(RegExp(substring(0, 1))) + 1;
      int y = int.parse(substring(1));
      return '${y.toStr(2)}${x.toStr(2)}';
    }
    return null;
  }

  String? gtpToYz2({int boardSize = 19}) {
    if (toLowerCase() == 'pass') {
      return '0000';
    }
    if (RegExp(r'[A-Z]\d{1,2}').hasMatch(this)) {
      String alpha = 'ABCDEFGHJKLMNOPQRST';
      int x = alpha.indexOf(RegExp(substring(0, 1))) + 1;
      int y = boardSize + 1 - int.parse(substring(1));
      return '${y.toStr(2)}${x.toStr(2)}';
    }
    return null;
  }

  gtpToChessStep(int bw, {int boardSize = 19}) {
    if (RegExp(r'[A-Z]\d{1,2}').hasMatch(this)) {
      String alpha = 'ABCDEFGHJKLMNOPQRST';
      int x = boardSize + 1 - int.parse(substring(1));
      int y = alpha.indexOf(RegExp(substring(0, 1))) + 1;
      return ChessStep(x, y, bw);
    }
    return null;
  }

  String yzToChessBoard({int boardSize = 19}) {
    String bw = substring(0, 1);
    int x = boardSize + 1 - int.parse(substring(1, 3));
    int y = int.parse(substring(3, 5));
    return bw + x.toStr(2) + y.toStr(2);
  }

  ///+0101转sgf,  ;B[A1]
  ///completed： 是否是完整sgf，包含两边的括号。
  String yzToSgf(
      {bool isCourse = false,
      int? boardSize,
      bool completed = false,
      bool isContainTitle = false}) {
    String sgf = boardSize == null ? '' : 'SZ[$boardSize]';
    if (!isCourse) {
      for (int i = 0; i < length / 5; i++) {
        sgf = '$sgf;${_yzToSgf(
          substring(5 * i, 5 * (i + 1)),
          boardSize: boardSize ?? 19,
        )}';
      }
    } else {
      String blackSteps = '';
      String whiteSteps = '';
      for (int i = 0; i < length; i++) {
        if (this[i] == '+') blackSteps += substring(i, i + 5);
        if (this[i] == '-') whiteSteps += substring(i, i + 5);
      }
      if (blackSteps.isNotEmpty) {
        sgf = 'AB';
        for (int i = 0; i < blackSteps.length / 5; i++) {
          sgf += _yzToSgf(
            blackSteps.substring(5 * i, 5 * (i + 1)),
            boardSize: boardSize ?? 19,
          ).substring(1);
        }
      }

      if (whiteSteps.isNotEmpty) {
        sgf += 'AW';
        for (int i = 0; i < whiteSteps.length / 5; i++) {
          sgf += _yzToSgf(
            whiteSteps.substring(5 * i, 5 * (i + 1)),
            boardSize: boardSize ?? 19,
          ).substring(1);
        }
      }
    }
    return completed
        ? "(;$sgf)"
        : isContainTitle
            ? "($sgf))"
            : sgf;
  }

  String yzToSgfAnswer({int? boardSize}) {
    String sgf = '';
    for (int i = 0; i < length / 5; i++) {
      sgf = '$sgf;${_yzToSgf(
        substring(5 * i, 5 * (i + 1)),
        boardSize: boardSize ?? 19,
      )}';
    }
    return sgf;
  }

  String yzToSgfMA(List<String> list) {
    String sgf = '';
    for (var element in list) {
      sgf += _yzToSgf('+' + element, type: 1);
    }
    return ';MA' + sgf;
  }

  // type 0-非标记题 1-标记题
  String _yzToSgf(String step, {int boardSize = 19, int type = 0}) {
    String sgf = "";
    String x, y;
    String bw = step.substring(0, 1);
    if (step.length == 5) {
      String currX = step.substring(3, 5);
      String currY = step.substring(1, 3);
      if (step.contains('0000')) {
        x = 't';
        y = 't';
      } else {
        x = String.fromCharCode(int.parse(currX) - 1 + 'a'.codeUnitAt(0));
        // y = String.fromCharCode('s'.codeUnitAt(0) - int.parse(currY) + 1);
        String end = String.fromCharCode('a'.codeUnitAt(0) + boardSize - 1);
        y = String.fromCharCode(end.codeUnitAt(0) - int.parse(currY) + 1);
        if (type == 1) {
          y = String.fromCharCode(
              end.codeUnitAt(0) - (boardSize - int.parse(currY)));
        }
      }

      if (type == 0) {
        if (bw == "+") {
          sgf = "B[" + x + y + "]";
        } else {
          sgf = "W[" + x + y + "]";
        }
      } else {
        sgf = "[" + x + y + "]";
      }
    }

    return sgf;
  }

  /// 获取题目的题干
  String sgfTitle(String sgfContent, int bw) {
    int index;
    if (sgfContent.contains('(;MA')) {
      index = sgfContent.indexOf("(;MA");
    } else {
      if (bw == 1) {
        index = sgfContent.indexOf("(;B");
      } else {
        index = sgfContent.indexOf("(;W");
      }

      if (index == -1) {
        if (bw == 1) {
          index = sgfContent.indexOf(";B");
        } else {
          index = sgfContent.indexOf(";W");
        }
      }
    }

    if (index == -1) {
      index = 0;
    }

    return sgfContent.substring(0, index);
  }

  /// +0101转坐标
  Coordinate? yzToCoordinate() {
    if (length != 5) return null;
    var bw = substring(0, 1);
    var position = substring(1);
    int x = int.parse(position.substring(2));
    int y = int.parse(position.substring(0, 2));
    return Coordinate(x, y, 19, bw: bw == '+' ? 1 : 2);
  }
}

extension ChessStepExt on ChessStep {
  String toYzStep({int boardSize = 19}) {
    String step = "";
    step += bw == Board.BLACK ? "+" : "-";
    if (x == 0 && y == 0) {
      return step + "0000";
    }
    step += (boardSize - x + 1).toStr(2);
    step += y.toStr(2);
    return step;
  }
}

extension CoordinateExt on Coordinate {
  ///该起步转换为gtp标准棋步，Q4  A16这种
  String toGtp() {
    String alpha = 'ABCDEFGHJKLMNOPQRST';
    if (x == 0 || y == 0) return "PASS";
    return "${alpha[x - 1]}$y";
  }
}

//------------
extension SgfNodeExt on SgfNode {
  ///棋谱
  String get chess {
    if (boardSize == 0) {
      boardSize = 19;
    }
    String s = "";
    for (var value in steps) {
      s +=
          "${value.bw == Board.BLACK ? "+" : "-"}${(boardSize - value.y + 1).toStr(2)}${value.x.toStr(2)}";
    }
    return s;
  }

  ///节点之前的全部棋步
  String backSteps({required int boardSize}) {
    String steps = "";
    backStepList().forEach((element) {
      // [3,4] => +1704
      steps += element.bw == Board.BLACK ? "+" : "-";
      steps += element.x == 0
          ? element.x.toStr(2)
          : (boardSize - element.x + 1).toStr(2);
      steps += element.y.toStr(2);
    });
    return steps;
  }

  ///3.0版数据结构转为类似2.0题目对象，仅仅适用于非多分支
  SgfCourse toCourse() {
    SgfCourse course = SgfCourse();

    var root = back(999);

    course.boardSize = root.boardSize;
    course.courseNode = root;

    for (var value in root.children) {
      List<SgfNode> answer = [];
      SgfNode? node = value;

      do {
        answer.add(node!);
        if (node.children.length == 1) {
          node = node.children[0];
        } else {
          node = null;
        }
      } while (node != null);

      course.answers.add(answer);
    }

    return course;
  }
}

class SgfCourse {
  int boardSize = 19;
  SgfNode courseNode = SgfNode();
  List<List<SgfNode>> answers = List.empty(growable: true);

  ///获取第几个解答分支的棋谱
  String answer(int num) {
    if (num >= answers.length) return '';
    List<SgfNode> _answers = answers[num];

    var chess = '';
    for (var element in _answers) {
      chess += element.chess;
    }
    return chess;
  }

  String tips(int num, int stepIndex) {
    if (num >= answers.length) return '';
    List<SgfNode> _answers = answers[num];
    return _answers[stepIndex].c;
  }

  ///解答是黑先还是白先
  int bw() {
    if (answer(0).substring(0, 1) == "+") {
      return 1;
    } else {
      return 2;
    }
  }

  /// 获取应答棋步
  SimpleMove? responseStep(String curAnswerSteps) {
    if (answers.isEmpty || curAnswerSteps.isEmpty) {
      return null;
    }
    List<int> answerSize = List.empty(growable: true);
    for (int i = 0; i < answers.length; i++) {
      if (answer(i).startsWith(curAnswerSteps)) {
        answerSize.add(i);
      }
    }
    if (answerSize.isNotEmpty) {
      int index = Random().nextInt(answerSize.length);
      index = answerSize[index];
      String steps = answer(index);
      String tip = tips(index, curAnswerSteps.length ~/ 5 - 1);
      if (steps.length > curAnswerSteps.length) {
        return SimpleMove.name(
            steps.substring(curAnswerSteps.length, curAnswerSteps.length + 5),
            tip,
            index);
      } else {
        return SimpleMove.name("", tip, index);
      }
    }

    return null;
  }

  @override
  String toString() {
    var a = '\n';
    answers.forEach((element) {
      a += '${element.toString()}\n';
    });
    return 'SgfCourse{\nboardSize: $boardSize, \ncourseNode: $courseNode, \nanswers: [$a]}';
  }
}

class SimpleMove {
  String step = '';
  String tips = '';
  int index;

  /// 随机到哪个解答
  SimpleMove.name(this.step, this.tips, this.index);
}

class Record {
  int position;
  int status;

  Record.name(this.position, this.status);
}
